package vip.specimen.system.utils;

import lombok.extern.slf4j.Slf4j;
import vip.specimen.system.common.component.RedisComponent;
import vip.specimen.system.common.component.SpringComponent;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Random;
import java.util.UUID;

/**
 * *@Author: 余浪人
 * *@Date：2021/2/4 14:18
 * *@Email:yulangren520@Gmail.com
 * *@QQ:1368419640
 **/
@Slf4j
public class VerificationCodeUtil {
    private String code;
    private RedisComponent redis = SpringComponent.getBean(RedisComponent.class);
    private String key;
    private String item;
    private long time;
    private final static Random RANDOM = new Random();
    private int width = 165; //验证码的宽
    private int height = 45; //验证码的高

    public VerificationCodeUtil(String key, String item, long time) {
        this.item = item;
        this.key = key;
        this.time = time;
    }

    /**
     * 颜色的设置
     *
     * @param fc
     * @param bc
     * @return
     */
    private static Color getRandomColor(int fc, int bc) {
        fc = Math.min(fc, 255);
        bc = Math.min(bc, 255);
        int r = fc + RANDOM.nextInt(bc - fc - 16);
        int g = fc + RANDOM.nextInt(bc - fc - 14);
        int b = fc + RANDOM.nextInt(bc - fc - 12);
        return new Color(r, g, b);
    }

    /**
     * 干扰线绘制
     *
     * @param g
     */
    private void drawLine(Graphics g) {
        int x = RANDOM.nextInt(width);
        int y = RANDOM.nextInt(height);
        int xl = RANDOM.nextInt(20);
        int yl = RANDOM.nextInt(10);
        g.drawLine(x, y, x + xl, y + yl);
    }

    /**
     * 设置字体
     *
     * @return
     */
    private Font getFont() {
        return new Font("Times New Roman", Font.ROMAN_BASELINE, 40);
    }

    /**
     * 绘制字符串
     *
     * @param g
     * @param randomStr 字符串
     * @param i
     * @return
     */
    private String drawString(Graphics g, String randomStr, int i) {
        g.setFont(getFont());
        g.setColor(getRandomColor(108, 190));
        g.translate(RANDOM.nextInt(3), RANDOM.nextInt(6));
        g.drawString(randomStr, 40 * i + 10, 25);
        return randomStr;
    }

    /**
     * 生成二维码 写入到redis并返回验证码字符串base64
     *
     * @return 验证码
     */
    public String getCode() {
        this.code = this.createCode();
        this.redis.hset(this.key, this.item, this.code, this.time); // 存储获取到的验证码
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics g = image.getGraphics();
        g.fillRect(0, 0, width, height);
        g.setColor(getRandomColor(105, 189));
        g.setFont(this.getFont());
        for (int i = 0; i < 30; i++) {
            drawLine(g);
        }
        for (int i = 0; i < this.code.length(); i++) {
            drawString(g, String.valueOf(this.code.charAt(i)), i);
        }
        g.dispose();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        String base64String = "data:image/jpg;base64,";
        try {
            ImageIO.write(image, "PNG", bos);
            base64String += Base64.getEncoder().encodeToString(bos.toByteArray());
        } catch (IOException e) {
            log.error("绘制验证码失败：" + e.getMessage());
        }
        return base64String;
    }

    /**
     * 判断验证码是否存在与正确
     *
     * @return 正确true 错误false
     */
    public boolean codeIsExist(String code) {
        String result = (String) this.redis.hget(this.key, this.item);
        if (null == code || null == result) {
            return false;
        } else if (code.toLowerCase().equals(result.toLowerCase())) {
            return true;
        }
        return false;
    }

    public void setCode(String code) {
        this.code = code;
    }

    private String createCode() {
        // TODO  字母类    数字类   混合类
        UUID uuid = UUID.randomUUID();
        String u = uuid.toString();
        u = u.substring(0, 4).toUpperCase();
        return u;
    }


    @Override
    public String toString() {
        return "验证码{" + "code='" + code + '\'' + '}';
    }
}
